
package jason.jeditplugin;

import jason.infra.centralised.StartNewAgentGUI;
import jason.mas2j.AgentParameters;
import jason.mas2j.ClassParameters;
import jason.mas2j.MAS2JProject;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileFilter;

import org.gjt.sp.jedit.Buffer;
import org.gjt.sp.jedit.View;
import org.gjt.sp.jedit.io.VFSManager;

public class NewModuleGUI extends StartNewAgentGUI {
	
	private static final long serialVersionUID = 1L;
	
	protected JTextField modName;
	Buffer projectBuffer;
	JasonID jasonID;
	
	View view;
	
	public NewModuleGUI(String title, Buffer projectBuffer, View view, String openDir, JasonID jasonID) {
		super(view, title, openDir);
		this.projectBuffer = projectBuffer;
		this.view = view;
		this.jasonID = jasonID;
	}
	
	protected void initComponents() {
		getContentPane().setLayout(new BorderLayout());
		
		// Fields
		
		modName = new JTextField(10);
		createField("Module name", modName, "The name of the module");
		
		agName = new JTextField(10);
		createField("Parent Agent", agName, "The name of the parent of this module");
		
		agSource = new JTextField(15);
		JButton sourceBrowseBt = new JButton("Browse");
		sourceBrowseBt.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				try {
					JFileChooser chooser = new JFileChooser(openDir);
					chooser.setDialogTitle("Select the AgentSpeak module source file");
					chooser.setFileFilter(new AslmFileFilter());
					// chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
					if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
						agSource.setText(chooser.getSelectedFile().toString());
					}
				} catch (Exception e) {
				}
			}
		});
		createField("Source", agSource, sourceBrowseBt, "The path for the source file of the module (e.g. ../asl/code.aslm). If left empty, the file will be the module's name + ." + MAS2JProject.ASM_EXT);
		
		JPanel p = new JPanel(new BorderLayout());
		p.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Module parameters", TitledBorder.LEFT, TitledBorder.TOP));
		p.add(pLabels, BorderLayout.CENTER);
		p.add(pFields, BorderLayout.EAST);
		
		getContentPane().add(p, BorderLayout.CENTER);
		getContentPane().add(createButtonsPanel(), BorderLayout.SOUTH);
	}
	
	protected boolean ok() {
		String agent = agName.getText().trim();
		if (!agent.isEmpty() && Character.isUpperCase(agent.charAt(0))) {
			agent = Character.toLowerCase(agent.charAt(0)) + agent.substring(1);
		}
		
		String module = modName.getText().trim();
		if (!module.isEmpty() && Character.isUpperCase(module.charAt(0))) {
			module = Character.toLowerCase(module.charAt(0)) + module.substring(1);
		}
		
		File source = null;
		String agSourceStr = agSource.getText().trim();
		if (!agSourceStr.isEmpty()) {
			source = new File(agSourceStr);
			
			if (!source.isAbsolute()) {
				source = new File(openDir + File.separator + agSourceStr);
			}
		}
		
		if (module.isEmpty() && source == null) {
			JOptionPane.showMessageDialog(this, "At least either the name of the module or its source has to be specified!");
			return false;
		}
		
		if (source == null) {
			source = new File(projectBuffer.getDirectory() + module + "." + MAS2JProject.ASM_EXT);
		} else if (module.isEmpty()) {
			module = source.getName().replaceFirst("\\.[^.]*$", "");
		}
		
		final String fAgent = agent;
		final String fModule = module;
		final File fSource = source;
		
		if (!fAgent.isEmpty()) {
			try {
				Buffer buffer = jasonID.getAgentBuffer(projectBuffer, fAgent);
				
				try {
					buffer.writeLock();
					String agentContent = buffer.getText(0, buffer.getLength());
					Matcher matcher = Pattern.compile("\n[ \\t\\x0B\\f]*\\{\\s*import\\s", Pattern.MULTILINE).matcher(agentContent);
					
					int pos;
					if (matcher.find()) {
						pos = matcher.start() + 1;
					} else {
						matcher = Pattern.compile("^\\s*//").matcher(agentContent);
						if (matcher.find()) {
							pos = agentContent.indexOf("\n", matcher.end()) + 1;
						} else {
							pos = 0;
						}
					}
					
					String localPath = fSource.getPath();
					String dir = buffer.getDirectory();
					int dirPos = localPath.toLowerCase().indexOf(dir.toLowerCase());
					if (dirPos != -1) localPath = localPath.substring(dirPos + dir.length());
					buffer.insert(pos, "{import " + fModule + "=\"" + localPath.replaceAll("\"", "\\\"") + "\"}" + "\n");
				} finally {
					buffer.writeUnlock();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		boolean newFile = !fSource.exists();
		Buffer nb = org.gjt.sp.jedit.jEdit.openFile(view, fSource.getAbsolutePath());
		if (newFile) {
			try {
				String agcode = Config.get().getTemplate("module.aslm");
				agcode = agcode.replace("<MODULE_NAME>", modName.getText());
				agcode = agcode.replace("<PROJECT_NAME>", projectBuffer.getName());
				final String agNameStr = agName.getText();
				agcode = agcode.replace("<AGENT_STRING>", (agNameStr.isEmpty() ? "" : "of Agent " + agNameStr + " "));
				agcode = agcode.replace("<AG_NAME>", agNameStr);
				
				if(!nb.isLoaded()) VFSManager.waitForRequests();
				nb.writeLock();
				nb.insert(0, agcode);
				nb.save(view, fSource.getAbsolutePath());
			} finally {
				nb.writeUnlock();
			}
		}
		
		return true;
	}
	
	class AslmFileFilter extends FileFilter {
		public boolean accept(File f) {
			if (f.getName().endsWith(MAS2JProject.AS_EXT) || f.getName().endsWith(MAS2JProject.ASM_EXT) || f.isDirectory()) {
				return true;
			} else {
				return false;
			}
		}
		
		public String getDescription() {
			return "AgentSpeak language module source";
		}
	}
	
}
